package io

import (
	"crypto/md5"
	"embed"
	"encoding/hex"
	"encoding/json"
	"io"
	"os"
	"path/filepath"
)

func WriteJson(fn string, v any) error {
	content, e := json.Marshal(v)
	if e != nil {
		return e
	}
	return os.WriteFile(fn, content, os.ModePerm)
}

func ReadJson(fn string, v any) error {
	f, e := os.Open(fn)
	if e != nil {
		return e
	}
	defer f.Close()
	content, e := io.ReadAll(f)
	if e != nil {
		return e
	}
	return json.Unmarshal(content, v)
}

// 复制文件
// src:源文件
// dst:目标文件或复制到的目录
// false_in_exist:true表示存在就返回失败，false表示存在存在则替换
// return os.PathError
func CopyFile(src, dst string, false_in_exist bool) error {
	fi, err := os.Lstat(dst)
	if err == nil && fi.IsDir() {
		dst = filepath.Join(dst, filepath.Base(src))
	}
	if false_in_exist {
		_, err = os.Lstat(dst)
		if err == nil || !os.IsNotExist(err) {
			return &os.PathError{
				Op:   "copy",
				Path: dst,
				Err:  os.ErrExist,
			}
		}
	}
	s, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !s.Mode().IsRegular() {
		return &os.PathError{
			Op:   "copy",
			Path: src,
			Err:  os.ErrNotExist,
		}
	}
	sf, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sf.Close()
	os.Remove(dst) //删除旧版本
	df, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer df.Close()
	_, err = io.Copy(df, sf)
	if err != nil {
		return err
	}
	return nil
}

func FileSystemCopy(fs embed.FS, name string, copyto string) (int64, error) {
	r, err := fs.Open(name)
	if err != nil {
		return 0, err
	}
	defer r.Close()
	w, err := os.Create(copyto)
	if err != nil {
		return 0, err
	}
	defer w.Close()
	return io.Copy(w, r)
}

func FileMD5(fp io.Reader) (string, error) {
	hash := md5.New()
	_, err := io.Copy(hash, fp)
	if err != nil {
		return "", err
	}
	v := hash.Sum(nil)
	return hex.EncodeToString(v[:]), nil
}
